#include "Config.h"
#include "wch/Thread.h"
#include "MsgHandler/MsgTypes.h"
#include "MsgHandler/MsgPool.h"
#include "Common/Atoi.h"
#include "Common/Itoa.h"
#include "Common/TimeUtil.h"
#include "Server.h"
#include "Network/Network.h"
#include "TcpServerWrapper.h"
#include "LogicWorker.h"
#include "DBCache/DBWorker.h"
#include "DBCache/DBCache.h"
#include "Server/ServerType.h"
#include "Cfg.h"
#include "DB/DBConnectionMgr.h"
#include "GameConfig.h"
#include "DB/DBExecutor.h"
#include "Server/IDGenerator.h"
#include "ServerClientManager.h"
#include "RoomManager.h"
#include "GameReportManager.h"

#include "HttpService.h"

const char * s_HelpInfo = "";
UInt8 SERVER_TYPE = 0;
UInt32 SERVER_ID = 0;
std::string SERVER_NAME;

DBConnectionMgr * gDataDBConnectionMgr;
DBConnectionMgr * gPlatDBConnectionMgr;
DBConnectionMgr * gObjectDBConnectionMgr;

Server::Server() : _logicWorker(nullptr), _dbWorker(nullptr), _tcpService(nullptr), _httpWorker(nullptr)
{

}

Server::~Server()
{
	SAFE_DELETE(_logicWorker);
	SAFE_DELETE(_dbWorker);
	SAFE_DELETE(_tcpService);
}

bool Server::init()
{
	Network::Initialize();
	TimeUtil::Init();
	cfg.load(getFilePath("conf/config-hall.lua"));
	MSGPOOL().init(THREAD_COUNT);
	//DB
	DBConfig dataConf = cfg.getDataConfig();
	gDataDBConnectionMgr = new DBConnectionMgr();
	gDataDBConnectionMgr->Init(dataConf._host.c_str(), dataConf._user.c_str(), dataConf._passwd.c_str(), dataConf._name.c_str(), 1, 1, dataConf._port);
	if (!gameConfig.loadGameConfig())
	{
		fprintf(stderr, "load GameConfig Error !\n");
		return false;
	}
	//
	DBConfig platConf = cfg.getPlatConfig();
	gPlatDBConnectionMgr = new DBConnectionMgr();
	gPlatDBConnectionMgr->Init(platConf._host.c_str(), platConf._user.c_str(), platConf._passwd.c_str(), platConf._name.c_str(), 3, 4, platConf._port);
	//
	DBConfig objectConf = cfg.getObjectConfig();
	gObjectDBConnectionMgr = new DBConnectionMgr();
	gObjectDBConnectionMgr->Init(objectConf._host.c_str(), objectConf._user.c_str(), objectConf._passwd.c_str(), objectConf._name.c_str(), 6, 8, objectConf._port);
	//
	_serverClientManager = new ServerClientManager();
	if (!_serverClientManager->load())
	{
		fprintf(stderr, "Server Client Manager Load Error !\n");
		return false;
	}
	//load all data
	_roomManager = new RoomManager();
	DBC().loadAll();
	//load all reports here
	_greportManager = new GameReportManager();
	if (!_greportManager->load())
	{
		fprintf(stderr, "Game Report Manager Load Error ~!\n");
		return false;
	}
	//
	_httpService = new HttpService(cfg.getHttpPort());
	_httpWorker = new Thread();
	_httpWorker->start(*_httpService);
	//
	_logicWorker = WorkerThread<LogicWorker>::Clone(new LogicWorker(Thread_Logic));
	_dbWorker = WorkerThread<DBWorker>::Clone(new DBWorker(Thread_DB));
	_tcpService = new Network::TcpServerWrapper(cfg.getTcpPort());
	return true;
}

void Server::run()
{
	_dbWorker->Run();
	_logicWorker->Run();
	_tcpService->Start();
	_tcpService->Join();
	fprintf(stdout, "Server Start Success~\n");
}

void Server::shutdown()
{
	_tcpService->UnInit();
	wch::Thread::sleep(2000);
	_logicWorker->Shutdown();
	_dbWorker->Shutdown();
}

void Server::unInit()
{
	MSGPOOL().unInit();
	gPlatDBConnectionMgr->UnInit();
	SAFE_DELETE(gPlatDBConnectionMgr);
	gObjectDBConnectionMgr->UnInit();
	SAFE_DELETE(gObjectDBConnectionMgr);
	Network::Uninitialize();
}

bool Server::parseCommandInfo(Int32 argc, char * argv[])
{
	SERVER_TYPE = Server_Hall;
	if (argc >= 2)
	{
		SERVER_ID = Atoi<UInt16>(argv[1]);
		SERVER_NAME = "Hall";
		SERVER_NAME.append(Itoa<UInt16>(SERVER_ID));
	}
	else
	{
		SERVER_ID = 1;
		SERVER_NAME = "Hall";
		SERVER_NAME.append(Itoa<UInt16>(SERVER_ID));
	}
	return true;
}

std::string& Server::getWorkDirectory()
{
	return _workerDirectory;
}

std::string Server::getFilePath(const std::string& path)
{
	std::string fullPath = _workerDirectory;
	fullPath.append(path);
	return fullPath;
}
